package com.csce.domain.entity.score.socket;

import com.csce.domain.entity.score.ScoreExExamPlaceAllot;
import com.csce.domain.entity.score.ScoreSheet;
import com.csce.domain.entity.score.vo.ScoreSheetExPlaceVo;
import com.doudou.core.container.MapUtil;
import com.doudou.core.container.SetUtil;
import com.doudou.core.lang.Option;
import com.doudou.core.str.StrUtil;
import lombok.Data;

import java.io.Serializable;
import java.util.*;

/**
 * @author zzxjs
 * @since 2023/11/29
 * 候考厅数据存储对象数据结构
 * 考试 > 考站 > 学员
 */
@Data
public class WaitingDataVo implements Serializable {
    private static final int MAX_WAITING_NUM = 7;

    /**
     * 考试编号
     */
    private Long examId;
    /**
     * 时段编号
     */
    private String timeId;
    /**
     * 是否可以展示姓名
     */
    private Boolean nameShow;

    /**
     * 维护学员的展示信息
     */
    private LinkedHashMap<String, WaitingPeoPleVo> peopleMap = new LinkedHashMap<>();
    //已经签到的学员
    private Map<Long, String> signOvers = MapUtil.hashMap();

    /**
     * 未安排考站的学员 [Q1、Q2]
     */
    private Set<String> unscheduleds = new LinkedHashSet<>();

    /**
     * 各个考站的排队人员
     */
    private LinkedHashMap<String, PlaceWaitingVo> placeWaitingMap = new LinkedHashMap<>();

    /**
     * 人员和评分表对应
     */
    private Map<String, ScoreSheetExPlaceVo> sheetMap = new HashMap<>();

    /**
     * 已考完的学员列表
     * placeId + "-" + index : {
     *     examinerType: scoreList
     * }
     */
    private Map<String, Map<String,LinkedList<ExPlacePeoPleVo>>> examOvers = new HashMap<>();

    public WaitingDataVo(Long examId, String timeId) {
        this.examId = examId;
        this.timeId = timeId;
    }

    /**
     * 添加房间模型 key： {房间id}-{index}
     */
    public void addPlaceWaitingModel(String exPlaceId, Long placeId, String placeName, Integer index, Integer waitNum, List<ScoreExExamPlaceAllot> examPlaceAllots, Map<Long, ScoreSheet> sheets) {
        PlaceWaitingVo placeWaitingVo = new PlaceWaitingVo(exPlaceId, placeId, placeName, index, waitNum);
        placeWaitingVo.addStuEmpty();
        peopleMap.put("#0", WaitingPeoPleVo.builder().code("#0").view(false).build());
        for (ScoreExExamPlaceAllot allot : examPlaceAllots) {
            String code = allot.getCode();
            sheetMap.put(exPlaceId + "-" + code, sheets.get(allot.getSheetId()).toExPlaceVo());
            peopleMap.put(code, WaitingPeoPleVo.builder().code(code).view(false).build());
            if (!placeWaitingVo.addStu(code)) {
                unscheduleds.add(code);
            }
        }
        unscheduleds.removeAll(placeWaitingVo.getStus());
        this.placeWaitingMap.put(exPlaceId + "-" + index, placeWaitingVo);
    }

    /**
     * 重新排序 unscheduleds，根据序号排序
     */
    public WaitingDataVo orderUnScheduleds() {
        unscheduleds = SetUtil.sort(unscheduleds, Comparator.comparing(key -> Integer.parseInt(StrUtil.subAfter(key, key.charAt(0), false))));
        return this;
    }

    public PlaceWaitingVo getPlaceWaiting(String placeId, int index) {
        return this.placeWaitingMap.get(placeId + "-" + index);
    }

    public WaitingPeoPleVo getWaitingPeoPleVo(String code) {
        return Option.of(this.peopleMap.get(code)).get(new WaitingPeoPleVo());
    }

    /**
     * 插入一个学员，查询到第一个没有学员编号的模型
     */
    public String insertStu(Long userId, String nickName) {
        String co = signOvers.get(userId);
        if (co != null) {
            return co;
        }
        Set<String> sortKeySet = SetUtil.sort(peopleMap.keySet(), Comparator.comparing(key -> Integer.parseInt(StrUtil.subAfter(key, key.charAt(0), false))));
        for (String code : sortKeySet) {
            WaitingPeoPleVo peoPleVo = peopleMap.get(code);
            if (!StrUtil.equals(peoPleVo.getCode(), "#0") && peoPleVo.getUserId() == null) {
                peoPleVo.setUserId(userId);
                peoPleVo.setView(true);
                if (this.nameShow) {//如果可以展示学员名称，插入学员名字
//                    peoPleVo.setUserName(DstUtil.userName(nickName));
                    peoPleVo.setUserName(nickName);
                }
                signOvers.put(userId, code);//添加已经签到的学员
                return code;
            }
        }
        return null;
    }

    /**
     * 根据考试和房间删除一个学员
     */
    public void deleteStu(String exPlaceId, int index, String code) {
        PlaceWaitingVo placeWaitingVo = placeWaitingMap.get(exPlaceId + "-" + index);
        if (placeWaitingVo != null) {
            if (code != null) {
                placeWaitingVo.stuRemove(code);
                //提出一位为安排考站的学员,添加到该考站
                String first = SetUtil.getFirst(unscheduleds);
                if (first != null && placeWaitingVo.addStu(first)) {
                    unscheduleds.remove(first);
                }
            }
        }
    }

    /**
     * 添加一个已考完学员
     */
    public void addExamOvers(String placeId, int index, ExPlacePeoPleVo people) {
        String key = placeId + "-" + index;
        Map<String,LinkedList<ExPlacePeoPleVo>> vos = Option.of(examOvers.get(key)).get(MapUtil.hashMap());
        LinkedList<ExPlacePeoPleVo> voss = Option.of(vos.get(people.getExaminerType())).get(new LinkedList<>());
        int updateIndex = -1;
        //遍历查找
        for (int i = 0; i < voss.size(); i++) {
            ExPlacePeoPleVo vo = voss.get(i);
            if (vo.getUserId().equals(people.getUserId()) &&
                vo.getAllotId().equals(people.getAllotId()) &&
                vo.getSheetId().equals(people.getSheetId()) &&
                vo.getExaminerId().equals(people.getExaminerId())) {
                updateIndex = i;
                break;
            }
        }
        if (updateIndex < 0) {//没找到，直接添加
            voss.add(people);
        } else {//重新打分
            voss.set(updateIndex, people);
        }
        vos.put(people.getExaminerType(),voss);
        examOvers.put(key, vos);
    }
}
